snapshot: Allow passing the bounds of the created paintable
authorBenjamin Otte <otte@redhat.com>
Mon, 2 Apr 2018 04:15:50 +0000 (06:15 +0200)
committerBenjamin Otte <otte@redhat.com>
Thu, 5 Apr 2018 12:56:39 +0000 (14:56 +0200)
This allows being more specific about the size.
It's useful in particular when the resulting render nodes might be
too small for the size, not only when they are too large. For the
latter case, using a clip node would be enough.

It also requires adding a clip node when rendering the resulting
paintable, but that should be optimized out by GtkSnapshot when not
necessary.

gtk/gtkcolorbutton.c
gtk/gtkcolorswatch.c
gtk/gtkiconview.c
gtk/gtkrendernodepaintable.c
gtk/gtkrendernodepaintableprivate.h
gtk/gtksnapshot.c
gtk/gtksnapshot.h
gtk/gtktextutil.c
gtk/gtktreeview.c
tests/testlist3.c

index 9fe9736a1eea668f60fafe0eda8cd2ab63f971a6..d5338664347b8ed219dfe8a43738cae1fb18a79d 100644 (file)
@@ -330,7 +330,7 @@ set_color_icon (GdkDragContext *context,
                              rgba,
                              &GRAPHENE_RECT_INIT(0, 0, 48, 32),
                              "ColorDragColor");
-  paintable = gtk_snapshot_free_to_paintable (snapshot);
+  paintable = gtk_snapshot_free_to_paintable (snapshot, NULL);
 
   gtk_drag_set_icon_paintable (context, paintable, 0, 0);
   g_object_unref (paintable);
index acd3298f7a2c90ded9748f9ef654a56e5a7d20a0..4872f4b667975f64bf6636f2178f9a2cb8917cdf 100644 (file)
@@ -175,7 +175,7 @@ drag_set_color_icon (GdkDragContext *context,
                              color,
                              &GRAPHENE_RECT_INIT(0, 0, 48, 32),
                              "ColorDragColor");
-  paintable = gtk_snapshot_free_to_paintable (snapshot);
+  paintable = gtk_snapshot_free_to_paintable (snapshot, NULL);
 
   gtk_drag_set_icon_paintable (context, paintable, 4, 4);
   g_object_unref (paintable);
index b9987b294a8d03db994e96c1fe2bc7eb883b5788..cbe65e5a3b9355286263e033a3191fd812f7c160 100644 (file)
@@ -6711,7 +6711,7 @@ gtk_icon_view_create_drag_icon (GtkIconView *icon_view,
                                        icon_view->priv->item_padding,
                                        icon_view->priv->item_padding,
                                        FALSE);
-          paintable = gtk_snapshot_free_to_paintable (snapshot);
+          paintable = gtk_snapshot_free_to_paintable (snapshot, NULL);
 
           return paintable;
        }
index 18c36a7a8c16e20e5e75753fb13cef1e0575e186..5ec8160946129ace596fdb70934e521fea0e9415 100644 (file)
@@ -28,6 +28,7 @@ struct _GtkRenderNodePaintable
   GObject parent_instance;
 
   GskRenderNode *node;
+  graphene_rect_t bounds;
 };
 
 struct _GtkRenderNodePaintableClass
@@ -42,29 +43,34 @@ gtk_render_node_paintable_paintable_snapshot (GdkPaintable *paintable,
                                               double        height)
 {
   GtkRenderNodePaintable *self = GTK_RENDER_NODE_PAINTABLE (paintable);
-  graphene_rect_t node_bounds;
+  gboolean needs_transform;
 
-  gsk_render_node_get_bounds (self->node, &node_bounds);
+  needs_transform = self->bounds.size.width != width ||
+                    self->bounds.size.height != height;
 
-  if (node_bounds.origin.x + node_bounds.size.width != width ||
-      node_bounds.origin.y + node_bounds.size.height != height)
+  if (needs_transform)
     {
       graphene_matrix_t transform;
 
       graphene_matrix_init_scale (&transform,
-                                  width / (node_bounds.origin.x + node_bounds.size.width),
-                                  height / (node_bounds.origin.y + node_bounds.size.height),
+                                  width / (self->bounds.size.width),
+                                  height / (self->bounds.size.height),
                                   1.0);
       gtk_snapshot_push_transform (snapshot,
                                    &transform,
                                    "RenderNodeScaleToFit");
-      gtk_snapshot_append_node (snapshot, self->node);
-      gtk_snapshot_pop (snapshot);
-    }
-  else
-    {
-      gtk_snapshot_append_node (snapshot, self->node);
     }
+
+  gtk_snapshot_push_clip (snapshot, &self->bounds, "RenderNodePaintableClip");
+  gtk_snapshot_offset (snapshot, self->bounds.origin.x, self->bounds.origin.y);
+
+  gtk_snapshot_append_node (snapshot, self->node);
+
+  gtk_snapshot_offset (snapshot, -self->bounds.origin.x, -self->bounds.origin.y);
+  gtk_snapshot_pop (snapshot);
+
+  if (needs_transform)
+    gtk_snapshot_pop (snapshot);
 }
 
 static GdkPaintableFlags
@@ -77,22 +83,16 @@ static int
 gtk_render_node_paintable_paintable_get_intrinsic_width (GdkPaintable *paintable)
 {
   GtkRenderNodePaintable *self = GTK_RENDER_NODE_PAINTABLE (paintable);
-  graphene_rect_t node_bounds;
 
-  gsk_render_node_get_bounds (self->node, &node_bounds);
-
-  return node_bounds.origin.x + node_bounds.size.width;
+  return self->bounds.size.width;
 }
 
 static int
 gtk_render_node_paintable_paintable_get_intrinsic_height (GdkPaintable *paintable)
 {
   GtkRenderNodePaintable *self = GTK_RENDER_NODE_PAINTABLE (paintable);
-  graphene_rect_t node_bounds;
-
-  gsk_render_node_get_bounds (self->node, &node_bounds);
 
-  return node_bounds.origin.y + node_bounds.size.height;
+  return self->bounds.size.height;
 }
 
 static void
@@ -132,15 +132,18 @@ gtk_render_node_paintable_init (GtkRenderNodePaintable *self)
 }
 
 GdkPaintable *
-gtk_render_node_paintable_new (GskRenderNode *node)
+gtk_render_node_paintable_new (GskRenderNode         *node,
+                               const graphene_rect_t *bounds)
 {
   GtkRenderNodePaintable *self;
 
   g_return_val_if_fail (GSK_IS_RENDER_NODE (node), NULL);
+  g_return_val_if_fail (bounds != NULL, NULL);
 
   self = g_object_new (GTK_TYPE_RENDER_NODE_PAINTABLE, NULL);
 
   self->node = gsk_render_node_ref (node);
+  self->bounds = *bounds;
 
   return GDK_PAINTABLE (self);
 }
index 1eba80ec3fcdb320f972b5dd8671530848740a4f..305eecffb6511d5af765caf0abb07e714e37943c 100644 (file)
@@ -28,7 +28,8 @@ G_BEGIN_DECLS
 
 G_DECLARE_FINAL_TYPE (GtkRenderNodePaintable, gtk_render_node_paintable, GTK, RENDER_NODE_PAINTABLE, GObject)
 
-GdkPaintable *  gtk_render_node_paintable_new   (GskRenderNode  *node);
+GdkPaintable *  gtk_render_node_paintable_new   (GskRenderNode         *node,
+                                                 const graphene_rect_t *bounds);
 
 G_END_DECLS
 
index 14514a9689d4eac1038e18933c435830d2f20779..c383364275f380df941dde07162244dadd28266d 100644 (file)
@@ -277,6 +277,8 @@ gtk_snapshot_free_to_node (GtkSnapshot *snapshot)
 /**
  * gtk_snapshot_free_to_paintable: (skip)
  * @snapshot: (transfer full): a #GtkSnapshot
+ * @size: (allow-none): The size of the resulting paintable
+ *     or %NULL to use the bounds of the snapshot
  *
  * Returns a paintable for the node that was
  * constructed by @snapshot and frees @snapshot.
@@ -284,11 +286,12 @@ gtk_snapshot_free_to_node (GtkSnapshot *snapshot)
  * Returns: (transfer full): a newly-created #GdkPaintable
  */
 GdkPaintable *
-gtk_snapshot_free_to_paintable (GtkSnapshot *snapshot)
+gtk_snapshot_free_to_paintable (GtkSnapshot           *snapshot,
+                                const graphene_size_t *size)
 {
   GdkPaintable *result;
 
-  result = gtk_snapshot_to_paintable (snapshot);
+  result = gtk_snapshot_to_paintable (snapshot, size);
   g_object_unref (snapshot);
 
   return result;
@@ -1286,6 +1289,8 @@ gtk_snapshot_to_node (GtkSnapshot *snapshot)
 /**
  * gtk_snapshot_to_paintable:
  * @snapshot: a #GtkSnapshot
+ * @size: (allow-none): The size of the resulting paintable
+ *     or %NULL to use the bounds of the snapshot
  *
  * Returns a paintable encapsulating the render node
  * that was constructed by @snapshot. After calling
@@ -1296,13 +1301,18 @@ gtk_snapshot_to_node (GtkSnapshot *snapshot)
  * Returns: (transfer full): a new #GdkPaintable
  */
 GdkPaintable *
-gtk_snapshot_to_paintable (GtkSnapshot *snapshot)
+gtk_snapshot_to_paintable (GtkSnapshot           *snapshot,
+                           const graphene_size_t *size)
 {
   GskRenderNode *node;
   GdkPaintable *paintable;
+  graphene_rect_t bounds;
 
   node = gtk_snapshot_to_node (snapshot);
-  paintable = gtk_render_node_paintable_new (node);
+  gsk_render_node_get_bounds (node, &bounds);
+  bounds.origin.x = 0;
+  bounds.origin.y = 0;
+  paintable = gtk_render_node_paintable_new (node, &bounds);
   gsk_render_node_unref (node);
 
   return paintable;
index 14cb20470d51587befc3c27f43d26f82bd9d9d55..7647a6b092e472f9200c45f6e2dce694aa4562a8 100644 (file)
@@ -58,12 +58,14 @@ GtkSnapshot *   gtk_snapshot_new                        (gboolean
 GDK_AVAILABLE_IN_ALL
 GskRenderNode * gtk_snapshot_free_to_node               (GtkSnapshot            *snapshot);
 GDK_AVAILABLE_IN_ALL
-GdkPaintable *  gtk_snapshot_free_to_paintable          (GtkSnapshot            *snapshot);
+GdkPaintable *  gtk_snapshot_free_to_paintable          (GtkSnapshot            *snapshot,
+                                                         const graphene_size_t  *size);
 
 GDK_AVAILABLE_IN_ALL
 GskRenderNode * gtk_snapshot_to_node                    (GtkSnapshot            *snapshot);
 GDK_AVAILABLE_IN_ALL
-GdkPaintable *  gtk_snapshot_to_paintable               (GtkSnapshot            *snapshot);
+GdkPaintable *  gtk_snapshot_to_paintable               (GtkSnapshot            *snapshot,
+                                                         const graphene_size_t  *size);
 
 GDK_AVAILABLE_IN_ALL
 gboolean        gtk_snapshot_get_record_names           (GtkSnapshot            *snapshot);
index 2507da9a843f7900760277bc904da1ffc8ce7350..a636c0ce199a0274cd5f7f5f0b711ede414f250b 100644 (file)
@@ -233,7 +233,7 @@ gtk_text_util_create_drag_icon (GtkWidget *widget,
                                &color);
   gtk_snapshot_append_layout (snapshot, layout, &color, "TextDragIcon");
 
-  paintable = gtk_snapshot_free_to_paintable (snapshot);
+  paintable = gtk_snapshot_free_to_paintable (snapshot, NULL);
   g_object_unref (layout);
 
   return paintable;
@@ -343,7 +343,7 @@ gtk_text_util_create_rich_drag_icon (GtkWidget     *widget,
   g_object_unref (layout);
   g_object_unref (new_buffer);
 
-  paintable = gtk_snapshot_free_to_paintable (snapshot);
+  paintable = gtk_snapshot_free_to_paintable (snapshot, &(graphene_size_t) { layout_width, layout_height });
 
   return paintable;
 }
index 64ddbcc2d98d9baecfc59abde20e3c0408e71e5d..cbdbb40c3ed3b58fef9fad0660e1fe35c6993158 100644 (file)
@@ -13944,7 +13944,7 @@ gtk_tree_view_create_row_drag_icon (GtkTreeView  *tree_view,
   gtk_treeview_snapshot_border (snapshot,
                                 &GRAPHENE_RECT_INIT(0, 0, bin_window_width + 2, background_area.height + 2));
 
-  paintable = gtk_snapshot_free_to_paintable (snapshot);
+  paintable = gtk_snapshot_free_to_paintable (snapshot, NULL);
 
   return paintable;
 }
index cfd1bcb6dac38778cd4d51b610b999286b06cd9a..cb604057e1ea46e51a46ae474dff963327102b94 100644 (file)
@@ -28,7 +28,7 @@ drag_begin (GtkWidget      *widget,
   gtk_style_context_remove_class (gtk_widget_get_style_context (row), "during-dnd");
 
   cairo_destroy (cr);
-  paintable = gtk_snapshot_free_to_paintable (snapshot);
+  paintable = gtk_snapshot_free_to_paintable (snapshot, NULL);
 
   gtk_widget_translate_coordinates (widget, row, 0, 0, &x, &y);
   gtk_drag_set_icon_paintable (context, paintable, -x, -y);